//
// C++ Implementation: cmdinteraction
//
// Description: 
//
//
// Author: Christophe Vandeplas <christophe@vandeplas.com>, (C) 2006
//
// Copyright: See COPYING file that comes with this distribution
//
//

#ifndef USE_LOADGEN_GUI   // this code is only if we are not using a gui


#include "cmdinteraction.h"
#include <iostream>
#include <sstream>
#include <string>
#include "Oxsipgen.h"
#include "SingleCall.h"
#include "eventhistory.h"


using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::istringstream;

#define INPUT_LINE_SIZE 200


CmdInteraction::CmdInteraction()
{
}


CmdInteraction::~CmdInteraction()
{
}


void CmdInteraction::grabInput()
{
    // this is the flow of the next code
    // DO {
    //   parsecommand
    // } WHILE  ( input != exit )
    // exit

    bool stayInLoop = false;
    string command;

    do {
        cout << "Oxsipgen> " ;
        getline(cin,command);

        stayInLoop = parseCommand(command);
    } while (stayInLoop);


}


bool CmdInteraction::parseCommand(string command)
{
    // if wants to exit app return false, else true


    // check if there are 2 strings
    string argument;
    int pos;
    if ( (pos=command.find_first_of(" ")) != string::npos ) {
        argument = command.substr(pos+1, string::npos);
        command = command.substr(0,pos);
    }

//     cout << "You said : "<<command <<endl;
//     cout << " argument: " << argument << endl;

    if ("help" == command ) {
        cout << "You requested some help. Here is a list of the possible commands:\n"
                "   help         - hey, you're using it right now...\n"
                "   list         - shows a list of all the threads, their ID, status and sceneFilename\n"
                "   show all     - show the history of all the threads\n"
                "   show <id>    - show the history of thread number 'id'\n"
                "   save all     - save the history of all the threads\n"
                "   save <id>    - save the history of thread number 'id'\n"
                "   stats        - give global short statistics about the running threads\n"
                "   status       - alias for 'stats'\n"
                "   threads      - alias for 'list'\n"
                "   quit         - quit the application while finishing the calls correctly\n"
                "   quitkill     - quit and kill the calls \n"
             << endl;
        return true;
    }

    if("list" == command ) {
        list();
        return true;
    }
    if("save" == command ) {
        if ("all" == argument ) save();
        else {
            // check argument validity
            int threadId=0;
            if (checkThreadIdValidity(argument, threadId)) save(threadId);
            else cout << "The specified 'id' is not valid" << endl;
        }
        return true;
    }

    if("show" == command ) {
        if ("all" == argument )
            for ( int i =0; i < Oxsipgen::getInstance()->getNumberOfThreads(); i++ )
                showHistory(i);
        else {
            int threadId=0;
            if (checkThreadIdValidity(argument, threadId)) showHistory(threadId);
            else cout << "The specified 'id' is not valid" << endl;
        }
        return true;
    }

    if("stats" == command ) {
        stats();
        return true;
    }

    if("status" == command ) {
        stats();
        return true;
    }

    if("threads" == command ) {
        list();
        return true;
    }
    if("quit" == command ) {
        cout << "Please wait while terminating all calls. This can take a _long_ time" << endl;
        Oxsipgen::getInstance()->terminateAllCalls();
        return false;
    }
    if("quitkill" == command ) {
        Oxsipgen::getInstance()->quit(true);// TODO does this work correctly?
        return false;
    }

    cout << "Command not understood, please try again or type 'help'" <<endl;
    return true;
}

bool CmdInteraction::checkThreadIdValidity(string &threadId, int &id )
{
    istringstream myStream(threadId);
    if (myStream>>id) {
        if ( id  < Oxsipgen::getInstance()->getNumberOfThreads() ) return true;
        return false;
    }
    return false;
}

void CmdInteraction::showHistory(int threadId, int numFromTail)
{
    cout << "*** History of threadId : " << threadId << " ***" <<endl; 
    EventHistory *history = Oxsipgen::getInstance()->getHistoryOfThread(threadId);
    unsigned int loopBegin=0;
    if ( numFromTail < history->size() && numFromTail !=0) loopBegin = history->size() - numFromTail;
    for (uint i =loopBegin; i < history->size() ; i++) {
        cout << "\t" << history->at(i) << "\n";
    }
    cout << endl;
}

/**
 * Outputs a list of the running threads of the Oxsipgen instance
 *    threadId   repeat     status       sceneFilename
 */
void CmdInteraction::list()
{
    const vector<LOADGEN_SINGLECALL_STRUCT> list =Oxsipgen::getInstance()->getListOfThreadsInfo();
    cout << "List of the threads" << endl;
    for (uint i =0; i < list.size() ; i++) {
        cout    << list.at(i).myNumber << "\t"
                << list.at(i).currentRepeat <<"/"<<list.at(i).repeatCount << "\t"
                << SingleCall::humanTranslateLoadgenState( list.at(i).state) << "\t"
                << list.at(i).filename
                << endl;
    }
}

void CmdInteraction::stats()
{
    cout    << "*** Statistics ***" << "\n"
            << " Number of simultanious calls : " << Oxsipgen::getInstance()->getNumberOfThreads() << "\n"
            << " Number of started calls      : " << SingleCall::getNumberOfStartedCalls() << "\n"
            << " Number of bad ended calls    : " << SingleCall::getNumberOfBadEndedCalls() << "\n"
            << " Percentage of good calls     : " << SingleCall::getPercentageGoodCalls()<< "%" << "\n"
            << endl;
}

void CmdInteraction::save(int threadId)
{
    bool stayInLoop = true;
    string filename;

    do {
        cout << "Enter the filename : " ;
        getline(cin,filename);
        if (filename != "" )stayInLoop=false;
    } while (stayInLoop);

    bool result =Oxsipgen::getInstance()->saveThreadsHistory(filename, threadId);
    if (!result) cerr << "ERROR: could not save file: '"<< filename << "'" <<endl;
    else cout << "File written correctly" << endl;

}


#endif // !USE_LOADGEN_GUI


